/*
 * Copyright 2022 André Claßen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * 可重排序项目组件
 * 提供在 Lazy 列表中支持拖拽重排序的项目组件
 */

package org.burnoutcrew.reorderable

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.zIndex

/**
 * Lazy列表中的可重排序项目
 *
 * @param reorderableState 重排序状态管理器
 * @param key 项目的唯一标识符
 * @param modifier 应用于项目的修饰符
 * @param index 项目的索引（可选）
 * @param orientationLocked 是否锁定拖拽方向
 * @param content 项目内容，参数表示是否正在拖拽
 */
@Composable
fun LazyItemScope.ReorderableItem(
    reorderableState: ReorderableState<*>,
    key: Any?,
    modifier: Modifier = Modifier,
    index: Int? = null,
    orientationLocked: Boolean = true,
    content: @Composable BoxScope.(isDragging: Boolean) -> Unit
) = ReorderableItem(reorderableState, key, modifier, Modifier.animateItem(), orientationLocked, index, content)

/**
 * Lazy网格中的可重排序项目
 *
 * @param reorderableState 重排序状态管理器
 * @param key 项目的唯一标识符
 * @param modifier 应用于项目的修饰符
 * @param index 项目的索引（可选）
 * @param content 项目内容，参数表示是否正在拖拽
 */
@Composable
fun LazyGridItemScope.ReorderableItem(
    reorderableState: ReorderableState<*>,
    key: Any?,
    modifier: Modifier = Modifier,
    index: Int? = null,
    content: @Composable BoxScope.(isDragging: Boolean) -> Unit
) = ReorderableItem(reorderableState, key, modifier, Modifier.animateItem(), false, index, content)

/**
 * 可重排序项目的核心实现
 *
 * @param state 重排序状态管理器
 * @param key 项目的唯一标识符
 * @param modifier 应用于项目的修饰符
 * @param defaultDraggingModifier 默认的拖拽修饰符
 * @param orientationLocked 是否锁定拖拽方向
 * @param index 项目的索引（可选）
 * @param content 项目内容，参数表示是否正在拖拽
 */
@Composable
fun ReorderableItem(
    state: ReorderableState<*>,
    key: Any?,
    modifier: Modifier = Modifier,
    defaultDraggingModifier: Modifier = Modifier,
    orientationLocked: Boolean = true,
    index: Int? = null,
    content: @Composable BoxScope.(isDragging: Boolean) -> Unit
) {
    // 判断当前项目是否正在被拖拽
    val isDragging = if (index != null) {
        index == state.draggingItemIndex
    } else {
        key == state.draggingItemKey
    }

    // 根据拖拽状态确定项目的修饰符
    val draggingModifier =
        if (isDragging) {
            // 正在拖拽时的修饰符：提高Z轴层级并应用位置变换
            Modifier
                .zIndex(1f) // 提高Z轴层级，确保拖拽项目在最上层
                .graphicsLayer {
                    // 根据滚动方向和锁定设置应用X轴变换
                    translationX =
                        if (!orientationLocked || !state.isVerticalScroll) state.draggingItemLeft else 0f
                    // 根据滚动方向和锁定设置应用Y轴变换
                    translationY =
                        if (!orientationLocked || state.isVerticalScroll) state.draggingItemTop else 0f
                }
        } else {
            // 检查是否是拖拽取消动画中的项目
            val cancel = if (index != null) {
                index == state.dragCancelledAnimation.position?.index
            } else {
                key == state.dragCancelledAnimation.position?.key
            }
            if (cancel) {
                // 拖拽取消动画中的修饰符：应用动画偏移
                Modifier.zIndex(1f)
                    .graphicsLayer {
                        // 应用取消动画的X轴偏移
                        translationX =
                            if (!orientationLocked || !state.isVerticalScroll) state.dragCancelledAnimation.offset.x else 0f
                        // 应用取消动画的Y轴偏移
                        translationY =
                            if (!orientationLocked || state.isVerticalScroll) state.dragCancelledAnimation.offset.y else 0f
                    }
            } else {
                // 非拖拽状态使用默认修饰符
                defaultDraggingModifier
            }
        }

    // 应用修饰符并渲染内容
    Box(modifier = modifier.then(draggingModifier)) {
        content(isDragging)
    }
}
